package cz.cvut.fit.mi.dpo.mvc.model;

import cz.cvut.fit.mi.dpo.mvc.model.elements.Circle;
import cz.cvut.fit.mi.dpo.mvc.model.elements.ElementCollection;
import cz.cvut.fit.mi.dpo.mvc.model.elements.Square;

import java.util.HashSet;
import java.util.Set;

/**
 * @author David Pertl
 * @author Martin Štekl <steklmar@fit.cvut.cz>
 */
public class Service implements IWritable, IReadable {

    private static final int DEFAULT_RADIUS = 5;
    private static final int DEFAULT_EDGE_LENGTH = 10;
    private ElementCollection<Circle> circles;
    private ElementCollection<Square> squares;
    private Set<IModelChangedListener> listeners = new HashSet<>();

    public Service() {
        init();
    }

    @Override
    public IWritable clear() {
        init();
        notifyAllListenersAboutChange();
        return this;
    }

    private void init() {
        circles = new ElementCollection<>();
        squares = new ElementCollection<>();
    }

    @Override
    public ElementCollection<Circle> getCircles() {
        return circles;
    }

    @Override
    public ElementCollection<Square> getSquares() {
        return squares;
    }

    @Override
    public IReadable addModelChangedListener(IModelChangedListener listener) {
        listeners.add(listener);
        return this;
    }

    @Override
    public IWritable createCircle(int x, int y) throws ZeroSizeException {
        return createCircle(x, y, DEFAULT_RADIUS);
    }

    @Override
    public IWritable createCircle(int x, int y, int r) throws ZeroSizeException {
        circles.add(new Circle(x, y, r));
        notifyAllListenersAboutChange();
        return this;
    }

    @Override
    public IWritable updateCircle(int id, int x, int y, int r) throws ZeroSizeException {
        circles.getById(id).setRadius(r).setX(x).setY(y);
        notifyAllListenersAboutChange();
        return this;
    }

    @Override
    public IWritable createSquare(int x, int y) throws ZeroSizeException {
        return createSquare(x, y, DEFAULT_EDGE_LENGTH);
    }

    @Override
    public IWritable createSquare(int x, int y, int a) throws ZeroSizeException {
        squares.add(new Square(x, y, a));
        notifyAllListenersAboutChange();
        return this;
    }

    @Override
    public IWritable updateSquare(int id, int x, int y, int a) throws ZeroSizeException {
        squares.getById(id).setEdgeLength(a).setX(x).setY(y);
        notifyAllListenersAboutChange();
        return this;
    }

    private void notifyAllListenersAboutChange() {
        for (IModelChangedListener listener : listeners) {
            listener.fire();
        }
    }

}
